﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Diagnostics;
using System.Configuration;
using System.ServiceModel;

using WcfCore;

namespace WcfSvcRunner
{
	class Program
	{
		public static string clientMachineName;
		public static string serviceMachineName;
		private static string remoteUser;
		private static string remotePassword;
		private static string wcfServerDir;
		private static string wcfServerExeName;
		private static string wcfServerExePath;
		private static string wcfServerConfigPath;
		private static string wcfServerBindingConfigPath;
		private static string wcfRemoteServerDir;
		private static string wcfRemoteServerExeName;
		private static string wcfRemoteServerExePath;
		private static string wcfRemoteServerConfigPath;
		private static string wcfRemoteServerBindingConfigPath;
		private static string wcfClientDir;
		private static string wcfClientExeName;
		private static string wcfClientExePath;
		private static string wcfClientConfigPath;
		private static string wcfClientBindingConfigPath;
		private static string logmanExePath;
		private static string psexecExePath;
		private static string pskillExePath;

		static void Main(string[] args)
		{
			Process.GetCurrentProcess().PriorityClass = ProcessPriorityClass.High;

			if (args.Length > 0)
			{
				Console.WriteLine("Usage: WcfSvcRunner");
				Console.ReadLine();
				return;
			}

			try
			{
				clientMachineName = ConfigurationManager.AppSettings["ClientMachineName"];
				serviceMachineName = ConfigurationManager.AppSettings["ServiceMachineName"];
				remoteUser = ConfigurationManager.AppSettings["RemoteUser"];
				remotePassword = ConfigurationManager.AppSettings["RemotePassword"];
				wcfServerDir = ConfigurationManager.AppSettings["WcfSvcHostDir"];
				wcfServerExeName = ConfigurationManager.AppSettings["WcfSvcHostExeName"];
				wcfServerExePath = Path.Combine(wcfServerDir, wcfServerExeName);
				wcfServerConfigPath = wcfServerExePath + ".config";
				wcfServerBindingConfigPath = Path.Combine(wcfServerDir, "Binding.config");
				wcfRemoteServerDir = ConfigurationManager.AppSettings["WcfRemoteSvcHostDir"];
				wcfRemoteServerExeName = ConfigurationManager.AppSettings["WcfRemoteSvcHostExeName"];
				wcfRemoteServerExePath = Path.Combine(wcfRemoteServerDir, wcfRemoteServerExeName);
				wcfRemoteServerConfigPath = wcfServerExePath + ".config";
				wcfRemoteServerBindingConfigPath = Path.Combine(wcfServerDir, "Bindings.config");
				wcfClientDir = ConfigurationManager.AppSettings["WcfClientHostDir"];
				wcfClientExeName = ConfigurationManager.AppSettings["WcfClientHostExeName"];
				wcfClientExePath = Path.Combine(wcfClientDir, wcfClientExeName);
				wcfClientConfigPath = wcfClientExePath + ".config";
				wcfClientBindingConfigPath = Path.Combine(wcfClientDir, "Bindings.config");
				logmanExePath = ConfigurationManager.AppSettings["LogManExePath"];
				psexecExePath = ConfigurationManager.AppSettings["PsExecExePath"];
				pskillExePath = ConfigurationManager.AppSettings["PsKillExePath"];

				foreach (PerformanceTestScope scope in WcfTestInput.RequestedScopes)
				{
					// We do not perform all combinations in Direct
					if (scope.Equals(PerformanceTestScope.Direct))
					{
						WcfTestInput directInput = new WcfTestInput(
							PerformanceTestScope.Direct,
							InstanceContextMode.PerCall,
							Bindings.netTcp,
							"Default",
							CallModes.TwoWay,
							SerializerFormats.DefaultSF);
						PerformTest(directInput);
						continue;
					}

					foreach (InstanceContextMode instancingMode in WcfTestInput.RequestedInstancingModes)
					{
						foreach (Bindings binding in WcfTestInput.RequestedBindings)
						{
							foreach (string bindingConfig in WcfTestInput.RequestedBindingConfigTags)
							{
								foreach (CallModes callMode in WcfTestInput.RequestedCallModes)
								{
									foreach (SerializerFormats serializer in WcfTestInput.RequestedSerializers)
									{
										WcfTestInput input = new WcfTestInput(scope, instancingMode, binding, bindingConfig, callMode, serializer);
										if (input.IsIllegalCombination)
										{
											WcfLogger.Log(string.Format("Illegal combination - skipping: {0}.", input.DisplayName));
											continue;
										}

										if (File.Exists(input.ConfigFileFullPath))
										{
											PerformTest(input);
										}
										else
										{
											WcfLogger.Log(string.Format("Configuration file for test {0} not found.", input.DisplayName));
										}
									}
								}
							}
						}
					}
				}
			}
			catch (Exception exc)
			{
				WcfLogger.LogException(exc);
			}
			finally
			{
			}
		}

		private static void PerformTest(WcfTestInput input)
		{
			WcfLogger.Log(string.Format("Starting test {0}.", input.DisplayName));

			if (File.Exists(wcfClientConfigPath))
			{
				File.SetAttributes(wcfClientConfigPath, FileAttributes.Normal);
			}
			File.Copy(input.ConfigFileFullPath, wcfClientConfigPath, true);

			//if (File.Exists(wcfClientBindingConfigPath))
			//{
			//    File.SetAttributes(wcfClientBindingConfigPath, FileAttributes.Normal);
			//}
			//File.Copy(input.BindingConfigFileFullPath, wcfClientBindingConfigPath, true);

			WcfTestInput.Serialize(input);
			CallGenericProcess(Program.wcfClientExePath, input.FileFullPath, true);

			KillEverything(input);
		}

		private static void CallGenericProcess(string exePath, string commandline, bool waitForExit)
		{
			Process psexec = new Process();
			psexec.StartInfo = new ProcessStartInfo(exePath, commandline);
			psexec.Start();
			if (waitForExit)
			{
				psexec.WaitForExit();
			}
		}

		private static void KillEverything(WcfTestInput input)
		{
			for (int i = 0; i < 2; i++)
			{
				string commandline;
				if (!input.Scope.Equals(PerformanceTestScope.Remote))
				{
					commandline = string.Format(@"-t {0}", "WcfSvcHost.exe");
				}
				else
				{
					commandline = string.Format(@"-t \\{0} -u {1} -p {2} {3}", serviceMachineName, remoteUser, remotePassword, "WcfSvcHost.exe");
				}

                WcfProcessHelper.StartChildProcessAndWaitForExit(pskillExePath, commandline);
            }

			for (int i = 0; i < 2; i++)
			{
				string commandline;
				if (!input.Scope.Equals(PerformanceTestScope.Remote))
				{
					commandline = string.Format(@"-t {0}", "WcfClientHost.exe");
				}
				else
				{
					commandline = string.Format(@"-t \\{0} -u {1} -p {2} {3}", serviceMachineName, remoteUser, remotePassword, "WcfClientHost.exe");
				}

                WcfProcessHelper.StartChildProcessAndWaitForExit(pskillExePath, commandline);
            }
		}
	}
}
